package generatepath;

import java.text.DecimalFormat;
import java.util.AbstractMap.SimpleEntry;
import java.util.ArrayList;
import java.util.LinkedList;

import org.apache.commons.collections.map.MultiKeyMap;

import calcul.CalculatePDV;
import calcul.CalculatePVV;
import calcul.Dictionar;
import enums.CableType;

public class Search {

	private static final String START = "C1";
	private static String END = "C11";
	private static ArrayList<String> drumuri;

	public static void main(String[] args) {
		// this graph is directional
		Graph graph = new Graph();
		graph.addTwoWayVertex("C1", "R1", CableType.T, 100);
		graph.addTwoWayVertex("C2", "R1", CableType.T, 80);
		graph.addTwoWayVertex("C3", "R1", CableType.T, 90);
		graph.addTwoWayVertex("C4", "R2", CableType.C2, 190);
		graph.addTwoWayVertex("C5", "R2", CableType.C5, 400);
		graph.addTwoWayVertex("C6", "R2", CableType.T, 90);
		graph.addTwoWayVertex("C7", "R3", CableType.T, 100);
		graph.addTwoWayVertex("C8", "R3", CableType.T, 50);
		graph.addTwoWayVertex("C9", "R3", CableType.C2, 150);
		graph.addTwoWayVertex("C10", "R4", CableType.C5, 200);
		graph.addTwoWayVertex("C11", "R4", CableType.T, 70);
		graph.addTwoWayVertex("C12", "R4", CableType.T, 80);
		graph.addTwoWayVertex("C13", "R5", CableType.T, 90);
		graph.addTwoWayVertex("C14", "R5", CableType.T, 100);
		graph.addTwoWayVertex("C15", "R5", CableType.T, 80);
		graph.addTwoWayVertex("C16", "R6", CableType.T, 100);
		graph.addTwoWayVertex("C17", "R6", CableType.T, 80);
		graph.addTwoWayVertex("C18", "R6", CableType.C2, 190);

		graph.addTwoWayVertex("R1", "R6", CableType.C2, 180);
		graph.addTwoWayVertex("R2", "R3", CableType.FB, 1100);
		graph.addTwoWayVertex("R2", "R4", CableType.C5, 400);
		graph.addTwoWayVertex("R4", "R5", CableType.T, 100);
		graph.addTwoWayVertex("R4", "R6", CableType.FL, 600);
		
		// graph.addTwoWayVertex("R4", "R1", CableType.FL, 600);

		LinkedList<String> visited;
		Search search = new Search();
		MultiKeyMap multiKeyMapCableTypeLength;
		CalculatePDV calculatePDV = new CalculatePDV();
		CalculatePVV calculatePVV = new CalculatePVV();
		Aranjamente arranAranjamente = new Aranjamente(18, 2);
System.out.println("Calcularea PDV");
		ArrayList<Integer[]> araAranj = arranAranjamente.getArranjamente();
		double max = 0, min = 999999;
		Dictionar maxPath = null, minPath = null;
		for (Integer[] integers : araAranj) {

			drumuri = new ArrayList();
			visited = new LinkedList();
			visited.add("C" + integers[0]);
			END = "C" + integers[1];
			search.breadthFirst(graph, visited);
			multiKeyMapCableTypeLength = graph.getMultiKeyMapCableTypeLength();
			
			for (Dictionar dictionar : calculatePDV.calculate(drumuri,	multiKeyMapCableTypeLength)) {

				if (max < dictionar.getPVD()) {
					maxPath = dictionar;
					max = dictionar.getPVD();
				}

				if (min > dictionar.getPVD()) {
					minPath = dictionar;
					min = dictionar.getPVD();
				}
				if (dictionar.getPVD() > 575) {
					System.out.println("Path: " + dictionar.getPath()
							+ " value: " + roundTwoDecimals(dictionar.getPVD()));
				}
			}

		}
		System.out.println("\nCalcularea PVV\n");
		for (Integer[] integers : araAranj) {
			drumuri = new ArrayList();
			visited = new LinkedList();
			visited.add("C" + integers[0]);
			END = "C" + integers[1];
			search.breadthFirst(graph, visited);
			multiKeyMapCableTypeLength = graph.getMultiKeyMapCableTypeLength();
			
			for (Dictionar dictionar : calculatePVV.calculate(drumuri,	multiKeyMapCableTypeLength)) {
				if(dictionar.getPVD() > 45){
					System.out.println("Path: " + dictionar.getPath()+ " value: " + roundTwoDecimals(dictionar.getPVD()));
				}
				
			}
			
		}
	}


	
	static double roundTwoDecimals(double d) {
        DecimalFormat twoDForm = new DecimalFormat("#.###");
    return Double.valueOf(twoDForm.format(d));
}



	private void breadthFirst(Graph graph, LinkedList<String> visited) {
		LinkedList<String> nodes = graph.adjacentNodes(visited.getLast());
		// examine adjacent nodes
		for (String node : nodes) {
			if (visited.contains(node)) {
				continue;
			}
			if (node.equals(END)) {
				visited.add(node);
				printPath(visited);
				visited.removeLast();
				break;
			}
		}
		// in breadth-first, recursion needs to come after visiting adjacent
		// nodes
		for (String node : nodes) {
			if (visited.contains(node) || node.equals(END)) {
				continue;
			}
			visited.addLast(node);
			breadthFirst(graph, visited);
			visited.removeLast();
		}
	}

	private void printPath(LinkedList<String> visited) {
		SimpleEntry s = new SimpleEntry(1, 2);
		String temp = "";
		for (String node : visited) {
			temp += node + ";";
		}
		drumuri.add(temp);
	}
}
